/**
 * 时间操作辅助类
 * @author Jerry
 * @version v1.0 DateUtil.java 2013-9-25 下午05:47:33
 * 
 */
package com.anjbo.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import org.apache.commons.lang3.StringUtils;

/**
 * DateUtil 时间操作公共类</br>
 * 如果要添加新的格式化格式，请先添加常量 :)
 * @author Jerry
 * @version v1.0 DateUtil.java 2013-9-25 下午05:47:33
 */
public class DateUtil {
	/**
	 * 格式：yyyy-MM-dd HH:mm:ss
	 */
	public static final String FMT_TYPE1 = "yyyy-MM-dd HH:mm:ss";
	/**
	 * 格式：yyyy-MM-dd
	 */
	public static final String FMT_TYPE2 = "yyyy-MM-dd";
	/**
	 * 格式：HH:mm:ss
	 */
	public static final String FMT_TYPE3 = "HH:mm:ss";
	/**
	 * 格式：yyyyMMddHHmmss
	 */
	public static final String FMT_TYPE4 = "yyyyMMddHHmmss";
	/**
	 * 格式：yyyyMMdd
	 */
	public static final String FMT_TYPE5 = "yyyyMMdd";
	/**
	 * 格式：HHmmss
	 */
	public static final String FMT_TYPE6 = "HHmmss";
	/**
	 * 格式：HHmmssSSS
	 */
	public static final String FMT_TYPE7 = "HHmmssSSS";
	/**
	 * 格式：yyyyMMddHHmmssSSS
	 */
	public static final String FMT_TYPE8 = "yyyyMMddHHmmssSSS";
	/**
	 * 格式：yyyy年MM月dd日
	 */
	public static final String FMT_TYPE9 = "yyyy年MM月dd日";
	/**
	 * 格式：yyyy-MM-dd HH:mm
	 */
	public static final String FMT_TYPE10 = "yyyy-MM-dd HH:mm";
	/**
	 * 格式：MM月dd日
	 */
	public static final String FMT_TYPE11 = "MM月dd日";
	/**
	 * 格式：MM-dd
	 */
	public static final String FMT_TYPE12 = "MM-dd";
	
	/**
	 * 返回指定格式化的日期<br>
	 * 如果 date为null，返回当前时间<br>
	 * 如果 fmt为null，返回 yyyy-MM-dd HH:mm:ss格式时间<br>
	 * @author Jerry
	 * @version v1.0 2013-9-25 下午06:11:18 
	 * @param date 时间
	 * @param fmt 格式化
	 * @return 指定格式化的日期
	 */
	public static String getDateByFmt(Date date,String fmt){
		if (StringUtils.isBlank(fmt)) {
			fmt = FMT_TYPE1;
		}
		SimpleDateFormat format = new SimpleDateFormat(fmt);
		if (date == null) {
			return format.format(new Date());
		}
		return format.format(date);
	}
	
	/**
	 * 获取 yyyyMMddHHmmss 格式时间<br>
	 * 如果date为null，返回当前时间
	 * @author Jerry
	 * @version v1.0 2013-9-25 下午05:56:57 
	 * @param date 时间
	 * @return 格式化后的时间字符串
	 */
	public static String getNowyyyyMMddHHmmss(Date date){
		SimpleDateFormat fmt = new SimpleDateFormat(FMT_TYPE4);
		if (date == null) {
			return fmt.format(new Date());
		}
		return fmt.format(date);
	}
	
	/**
	 * 获取 yyyyMMdd 格式时间<br>
	 * 如果date为null，返回当前时间
	 * @author Jerry
	 * @version v1.0 2013-9-25 下午05:57:25 
	 * @param date 时间
	 * @return 格式化后的时间字符串
	 */
	public static String getNowyyyyMMdd(Date date){
		SimpleDateFormat fmt = new SimpleDateFormat(FMT_TYPE5);
		if (date == null) {
			return fmt.format(new Date());
		}
		return fmt.format(date);
	}
	
	/**
	 * 获取 HHmmss 格式时间 <br>
	 * 如果date为null，返回当前时间
	 * @author Jerry
	 * @version v1.0 2013-9-25 下午05:59:21 
	 * @param date 时间
	 * @return 格式化后的时间字符串
	 */
	public static String getNowHHmmss(Date date){
		SimpleDateFormat fmt = new SimpleDateFormat(FMT_TYPE6);
		if (date == null) {
			return fmt.format(new Date());
		}
		return fmt.format(date);
	}
	
	/**
	 * 获取 HHmmssSSS 格式时间<br>
	 * 如果date为null，返回当前时间
	 * @author Jerry
	 * @version v1.0 2013-9-25 下午05:59:25 
	 * @param date 时间
	 * @return 格式化后的时间字符串
	 */
	public static String getNowHHmmssSSS(Date date){
		SimpleDateFormat fmt = new SimpleDateFormat(FMT_TYPE7);
		if (date == null) {
			return fmt.format(new Date());
		}
		return fmt.format(date);
	}
	
	/**
	 * 获取 yyyyMMddHHmmssSSS 格式时间<br>
	 * 如果date为null，返回当前时间
	 * @author Jerry
	 * @version v1.0 2013-9-25 下午05:59:33 
	 * @param date 时间
	 * @return 格式化后的时间字符串
	 */
	public static String getNowyyyyMMddHHmmssSSS(Date date){
		SimpleDateFormat fmt = new SimpleDateFormat(FMT_TYPE8);
		if (date == null) {
			return fmt.format(new Date());
		}
		return fmt.format(date);
	}

	/**
	 * 获取 yyyy-MM-dd HH:mm:ss 格式时间<br>
	 * 如果date为null，返回当前时间
	 * @author Jerry
	 * @version v1.0 2013-9-25 下午05:59:36 
	 * @param date 时间
	 * @return 格式化后的时间字符串
	 */
	public static String getSimpleDate(Date date){
		SimpleDateFormat fmt = new SimpleDateFormat(FMT_TYPE1);
		if (date == null) {
			return fmt.format(new Date());
		}
		return fmt.format(date);
	}
	/**
	 * 获取 yyyy-MM-dd HH:mm:ss 格式时间<br>
	 * 如果date为null，返回当前时间
	 * @author Jamin
	 * @version v1.0 2013-10-11 下午05:59:36 
	 * @param date 时间
	 * @return 格式化后的时间字符串
	 */
	public static Date getStartTime() {
		Calendar c = Calendar.getInstance();
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		return c.getTime();
	}
	
	/**
	 * 获取当前时间  N天前后   的日期</br>
	 * 如：-1=当前日期  一天前  的日期，1=当前日期  一天后  的日期
	 * @author Jerry
	 * @version v1.0 2013-10-14 下午02:47:39 
	 * @param day 天数
	 * @param fmt_type 格式化类型
	 * @return 格式化后的日期
	 */
	public static String getDayBeforeDate(int day,String fmt_type){
		Calendar rightNow = Calendar.getInstance();
		rightNow.add(Calendar.DAY_OF_MONTH, day);
		return getDateByFmt(rightNow.getTime(), fmt_type);
	}
	public static String getDayBeforeDate(int day,String date,String fmt_type){
		Calendar rightNow = Calendar.getInstance();
		rightNow.setTime(parse(date, fmt_type));
		rightNow.add(Calendar.DAY_OF_MONTH, day);
		return getDateByFmt(rightNow.getTime(), fmt_type);
	}
	
	/**
	 * 获取当前时间  N个月前后  日期，n可为正负整数</br>
	 * 如：-1=当前日期  一月前  的日期，1=当前日期  一月后  的日期
	 * @author Jerry
	 * @version v1.0 2013-10-14 下午02:44:03 
	 * @param month 月数
	 * @param fmt_type 格式化类型
	 * @return 按照参数 fmt_type 格式化后的日期
	 */
	public static String getMonthBeforeDate(int month,String fmt_type){
		Calendar rightNow = Calendar.getInstance();
		rightNow.add(Calendar.MONTH, month);
		return getDateByFmt(rightNow.getTime(), fmt_type);
	}
	/**
	 * 将字符串的转换成date类型</br>
	 * @author lifh
	 * @version v1.0 2013-11-28 下午10:44:03 
	 * @param date 日期
	 * @param fmt_type 格式化类型
	 * @return 按照参数 fmt_type 格式化后的日期
	 */
	public static Date parse(String date,String fmt_type ){
		SimpleDateFormat fmt = new SimpleDateFormat(fmt_type);
		try {
			if (date != null) {
				return fmt.parse(date);
			}
		} catch (ParseException e) {
		}
		return new Date();
	}
    /**
     * 判断当前日期是星期几<br>
     * <br>
     * @param pTime 修要判断的时间<br>
     * @return dayForWeek 判断结果<br>
     * @Exception 发生异常<br>
     */
	 public static int dayForWeek(String pTime) {
		  SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		  Calendar c = Calendar.getInstance();
		  try {
			c.setTime(format.parse(pTime));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		  int dayForWeek = 0;
		  if(c.get(Calendar.DAY_OF_WEEK) == 1){
			  dayForWeek = 7;
		  }else{
			  dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
		  }
		  return dayForWeek;
	 }
	 /**
	 * 获取当前时间后一天，并排除周六周天
	 * @param date
	 * @return
	 */
	public static String lastDate(String date){
		String last = DateUtil.getDayBeforeDate(1, date, DateUtil.FMT_TYPE2);
		int week = DateUtil.dayForWeek(last);
		if(week==6||week==7){
			return lastDate(last);
		}
		return last;
	}
	public static String weekName(int week){
		String weekNames[] = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };
		try {
			return weekNames[week-1];
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * 获取最近一周倒序集合数据
	 * @author limh
	 * @date 2015-8-15 下午04:42:00
	 * @param defaultVal 默认值
	 * @return
	 *  key 日期字符串 如：08-15
	 *  <br>
	 *  val defaultVal值
	 */
	public static Map<String,Object> getWeekDescMap(Object defaultVal){
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		for(int i=0;i<=6;i++){
			map.put(DateUtil.getDayBeforeDate(-i, DateUtil.FMT_TYPE12), defaultVal);
		}
		return map;
	}
	
	/**
	 * 获取最近一周顺序集合数据
	 * @return
	 */
	public static Map<String,Object> getWeekAscMap(){
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		for(int i=6;i>=0;i--){
			map.put(DateUtil.getDayBeforeDate(-i, DateUtil.FMT_TYPE12), null);
		}
		return map;
	}
	
	/**
	 * 获取最近一月顺序集合数据
	 * @author hx
	 * @date 2016-10-29
	 * @param defaultVal 默认值
	 * @return
	 *  key 日期字符串 如：08-15
	 *  <br>
	 *  val defaultVal值
	 */
	public static Map<String,Object> getMothAscMap(Object defaultVal){
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		for(int i=31;i>=0;i--){
			map.put(DateUtil.getDayBeforeDate(-i, DateUtil.FMT_TYPE12), defaultVal);
		}
		return map;
	}
	
	/**
	 * 获取月数顺序集合数据
	 * @param moth	指定月数
	 * @return
	 */
	public static List<String> getMothDescList(int moth){
		List<String> lists = new ArrayList<String>();
		if (moth > 0) {
			Calendar cal = Calendar.getInstance();  
	        cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)+1); //要先+1,才能把本月的算进去</span>  
	        for(int i=0; i<moth; i++){  
	            cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)-1); //逐次往前推1个月  
	            lists.add(new SimpleDateFormat("yyyy-MM").format(cal.getTime()));  
	        }
		}
        return lists;
	}
	
	public static Map<String,Object> getWeekDescMap(String startTime,String endTime,Object defaultVal){
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		if(StringUtils.isEmpty(startTime)){
			return getWeekDescMap(defaultVal);
		}
		if(StringUtils.isEmpty(endTime)){
			endTime = getDateByFmt(new Date(),FMT_TYPE2);
		}
		String tempTime = endTime;
		while(!tempTime.equals(startTime)){
			tempTime = DateUtil.getDayBeforeDate(-1,tempTime, DateUtil.FMT_TYPE2);
			map.put(tempTime.substring(5), defaultVal);
		}
		return map;
	}
	/**
	 * 获取当前年下的几个周倒序集合数据
	 * @author limh
	 * @date 2015-8-19 上午11:53:50
	 * @param weeks 周数
	 * @return
	 */
	public static Map<String,Object> getYearWeekDescMap(int weeks){
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		for(int i=0;i<weeks;i++){
			String str="";
			if(i==0){
				str="本周";
			}else if(i==1){
				str="上周";
			}else{
				str = getWeekOfMonth(-i);
			}
			map.put(getDateKey(new Date(),-i), str);
		}
		return map;
	}
	/**
	 * 获取当前年下的几个月倒序集合数据
	 * @author limh
	 * @date 2015-8-19 上午11:53:50
	 * @param months 月数
	 * @return
	 */
	public static Map<String,Object> getYearMonthDescMap(int months){
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		for(int i= 0 ;i<months;i++){	   
			SimpleDateFormat sdf = new SimpleDateFormat("MM");
	        Calendar cd = Calendar.getInstance();
	        cd.setTime(new Date());
	 		cd.add(Calendar.MONTH, -i);
			map.put(getYYYYMM(cd.getTime()), sdf.format(cd.getTime())+"月");
		}
		return map;
	}
	public static String getWeekOfMonth(int weeks) {
		StringBuffer sb = new StringBuffer();
		 Calendar cal = Calendar.getInstance();
		 cal.add(Calendar.WEEK_OF_YEAR, weeks);

		 int day_of_week = cal.get(Calendar.DAY_OF_WEEK) - 2;
		 cal.add(Calendar.DATE, -day_of_week);
		 sb.append(getDateByFmt(cal.getTime(),FMT_TYPE12));
		 sb.append("至");
		 cal.add(Calendar.DATE, 6);
		 sb.append(getDateByFmt(cal.getTime(),FMT_TYPE12));
		 return sb.toString();
	}
//	public static void main(String[] args) {
//		//System.out.println(getYearMonthDescMap(4));
//		Iterator<String> it = getWeekDescMap("2015-11-20","2015-12-20",null).keySet().iterator();
//		while(it.hasNext()){
//			System.out.println(it.next());
//		}
//	}
	public static Date nextMonth(Date date,int month){
		Calendar cd = Calendar.getInstance();
		cd.setTime(date);
		cd.add(Calendar.MONTH, month);
		return cd.getTime();
	}
    
    public static Date nextDay(Date date,int days){
		Calendar cd = Calendar.getInstance();
		cd.setTime(date);
		cd.add(Calendar.DATE, days);
		return cd.getTime();
	}
    
    public static Date nextHours(Date date,int hours){
		Calendar cd = Calendar.getInstance();
		cd.setTime(date);
		cd.add(Calendar.HOUR, hours);
		return cd.getTime();
	}
    
    public static Date nextYear(Date date,int years){
		Calendar cd = Calendar.getInstance();
		cd.setTime(date);
		cd.add(Calendar.YEAR, years);
		return cd.getTime();
	}
    
    public static int getWeekNumber(Date date,int weeks){ 
         Calendar cd = Calendar.getInstance();
         cd.setFirstDayOfWeek(Calendar.SATURDAY);
         cd.setTime(date);
 		 cd.add(Calendar.WEEK_OF_YEAR, weeks);
 		 
         return cd.get(Calendar.WEEK_OF_YEAR);
    }
    
    public static Date getWeekDate(Date date,int weeks){ 
        Calendar cd = Calendar.getInstance();
        cd.setFirstDayOfWeek(Calendar.SATURDAY);
        cd.setTime(date);
		cd.add(Calendar.WEEK_OF_YEAR, weeks);
		int week = cd.get(Calendar.WEEK_OF_YEAR);
		cd.add(Calendar.DAY_OF_MONTH, -7);
		if(week<cd.get(Calendar.WEEK_OF_YEAR)){  
		    cd.add(Calendar.YEAR, 1);
		}else{
			
		}
		return cd.getTime();
   }
    
    public static String getYYYYMM(Date date){
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
    	return sdf.format(date);
    }
    
    public static int getMonthNumber(Date date,int months){ 
    	SimpleDateFormat sdf = new SimpleDateFormat("MM");
        Calendar cd = Calendar.getInstance();
        cd.setTime(date);
 		cd.add(Calendar.MONTH, months);
        return Integer.valueOf(sdf.format(cd.getTime()));
    
     }
    
    public static String getDateKey(Date date ,int weeks){
        Calendar cd = Calendar.getInstance();
        cd.setFirstDayOfWeek(Calendar.SUNDAY);
        cd.setTime(date);
		cd.add(Calendar.WEEK_OF_YEAR, weeks);
		int week = cd.get(Calendar.WEEK_OF_YEAR);
		cd.add(Calendar.DAY_OF_MONTH, -7);
		if(week<cd.get(Calendar.WEEK_OF_YEAR)){  
			week = cd.get(Calendar.WEEK_OF_YEAR) + 1 ;
		}else{
			cd.add(Calendar.DAY_OF_MONTH, 7);
			if(cd.get(Calendar.YEAR) == 2016 || cd.get(Calendar.YEAR) == 2017){
				week -= 1;
			}
		}
    	return String.format("%1$tY%2$02d",cd.getTime(),week);
    }
    
	public static String getGMT(Date dateCST) { 
		   DateFormat df = new SimpleDateFormat("EEE MMM yyyy HH:mm:ss z 0800 (中国标准时间)", Locale.ENGLISH); 
		   df.setTimeZone(TimeZone.getTimeZone("GMT")); // Fri Nov 13 2015 12:03:14 GMT 0800 (中国标准时间)
		   return(df.format(dateCST)); 
	}
}
